import os
import sys
import config
import smtplib
from email.mime.text import MIMEText
from email.header import Header
from time import strftime
from collections import Iterable
import traceback
import contextlib
import requests


class MsgChain:
	def __init__(self):
		self.content = []

	def addPlain(self, msg):
		self.content.append({'type': 'Plain', 'text': msg})

	def append(self, chain):
		self.content.extend(chain.content)


def log(*objects, sep=' ', end='\n', file=config.utils.log.file,
		print_=config.utils.log.print, flush=config.utils.log.flush):
	if print:
		print(strftime('%Y-%m-%d %H:%M:%S'), *objects, sep=sep, end=end, flush=flush)
	with open(file, 'a', encoding='utf-8') as f:
		print(strftime('%Y-%m-%d %H:%M:%S'), *objects, sep=sep, end=end, file=f, flush=flush)


def LOG(*objects, sep=' ', end='\n', file=config.utils.LOG.file,
		print_=config.utils.LOG.print, flush=config.utils.LOG.flush):
	if print:
		print(strftime('%Y-%m-%d %H:%M:%S'), *objects, sep=sep, end=end, flush=flush)
	with open(file, 'a', encoding='utf-8') as f:
		print(strftime('%Y-%m-%d %H:%M:%S'), *objects, sep=sep, end=end, file=f, flush=flush)


def mail(content, subject=config.utils.mail.subject):
	msg = MIMEText(content, 'plain', 'utf-8')
	msg['From'] = Header(config.utils.mail.from_, 'utf-8')
	msg['To'] = Header(config.utils.mail.to, 'utf-8')
	msg['Subject'] = Header(subject, 'utf-8')
	try:
		smtpObj = smtplib.SMTP()
		smtpObj.connect(config.utils.mail.host, config.utils.mail.port)
		smtpObj.login(config.utils.mail.user, config.utils.mail.pass_)
		smtpObj.sendmail(config.utils.mail.sender, receivers, msg.as_string())
	# log(config.utils.mailSucceedMsg)
	except Exception:
		LOG(config.utils.mailFailMsg)


@contextlib.contextmanager
def trying(toStop=config.utils.trying.toStop, toLOG=config.utils.trying.toLOG,
		   toLog=config.utils.trying.toLog, toMail=config.utils.trying.toMail,
		   toMsg=config.utils.trying.toMsg):
	try:
		yield
	except KeyboardInterrupt:
		s = config.utils.trying.interruptedMsg
		if toLOG:
			LOG(s)
		elif tolog:
			log(s)
		exit(0)
	except Exception:
		s = config.utils.trying.exceptionMsg + '\n' + traceback.format_exc()
		if toLOG:
			LOG(s)
		elif toLog:
			log(s)
		if toMail:
			mail(s)
		if toMsg:
			chain = MsgChain()
			chain.addPlain(s)
			sendFriends(chain, config.admins)
		if toStop:
			exit(-1)
	except:
		s = config.utils.trying.errorMsg
		if toLOG:
			LOG(s)
		elif toLog:
			log(s)
		if toMail:
			mail(s)
		if toMsg:
			chain = MsgChain()
			chain.addPlain(s)
			sendFriends(chain, config.admins)
		if toStop:
			exit(-1)

def par(page, **kwargs):
	page += '?'
	for key, val in kwargs.items():
		page += f'{key}={val}&'
	return page[:-1]


def getRaw(page, **kwargs):
	# log(page, kwargs)
	r = requests.get(config.utils.requestPrefix + page, json=kwargs)
	# log(r.text)
	return r


def postRaw(page, **kwargs):
	# log(page, kwargs)
	r = requests.post(config.utils.requestPrefix + page, json=kwargs)
	# log(r.text)
	return r


def get(page, **kwargs):
	result = getRaw(page, **kwargs).json()
	if result == {'code': 0, 'msg': 'success', 'messageId': -1}:
		LOG(config.utils.bannedMsg)
	return result


def post(page, **kwargs):
	result = postRaw(page, **kwargs).json()
	if result == {'code': 0, 'msg': 'success', 'messageId': -1}:
		LOG(config.utils.bannedMsg)
	return result

def sendFriends(chain, friends):
	if not isinstance(friends, Iterable):
		friends = [friends]
	for friend in friends:
		post('sendFriendMessage', target=friend, messageChain=chain.content)

def sendGroups(chain, groups):
	if not isinstance(groups, Iterable):
		groups = [groups]
	for group in groups:
		post('sendGroupMessage', target=group, messageChain=chain.content)

def sendFriendsAndGroups(chain, friends=[], groups=[]):
	sendFriends(chain, friends)
	sendGroups(chain, groups)